using System;
using System.Linq;
using System.Windows;
using System.Windows.Documents;
using WPFTemplateLib.Adorners;
/*
* 源码已托管：https://gitee.com/dlgcy/WPFTemplateLib
* 版本：2025年7月12日
*/
namespace WPFTemplateLib.Attached
{
	/// <summary>
	/// 附加属性帮助类，实现通过 Xaml 附加元素到装饰层，改造（Copilot）自 AttachAdornerBehavior，解决设计时不显示的问题。
	/// </summary>
	public static class AttachAdornerHelper
	{
		#region IsShowAdorner 附加属性
		/// <summary>
		/// 获取是否显示 Adorner。
		/// </summary>
		public static bool GetIsShowAdorner(DependencyObject obj) => (bool)obj.GetValue(IsShowAdornerProperty);
		/// <summary>
		/// 设置是否显示 Adorner。
		/// </summary>
		public static void SetIsShowAdorner(DependencyObject obj, bool value) => obj.SetValue(IsShowAdornerProperty, value);
		/// <summary>
		/// 附加属性：是否显示 Adorner。
		/// </summary>
		public static readonly DependencyProperty IsShowAdornerProperty =
			DependencyProperty.RegisterAttached("IsShowAdorner", typeof(bool), typeof(AttachAdornerHelper),
				new PropertyMetadata(true, OnIsShowAdornerChanged));
		/// <summary>
		/// IsShowAdorner 属性变更回调。
		/// </summary>
		private static void OnIsShowAdornerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			if(d is UIElement element)
			{
				if(GetElement(element) != null)
				{
					RegisterIsVisibleChanged(element);
					RegisterDataContextChanged(element);
					UpdateAdornerVisibility(element);
				}
				else
				{
					RemoveAdorner(element);
					UnregisterIsVisibleChanged(element);
					UnregisterDataContextChanged(element);
				}
			}
		}
		#endregion

		#region Element 附加属性
		/// <summary>
		/// 获取要添加到装饰层的元素或模板。
		/// </summary>
		public static object GetElement(DependencyObject obj) => obj.GetValue(ElementProperty);
		/// <summary>
		/// 设置要添加到装饰层的元素或模板。
		/// </summary>
		public static void SetElement(DependencyObject obj, object value) => obj.SetValue(ElementProperty, value);
		/// <summary>
		/// 附加属性：要添加到装饰层的元素或 DataTemplate。
		/// </summary>
		public static readonly DependencyProperty ElementProperty =
			DependencyProperty.RegisterAttached("Element", typeof(object), typeof(AttachAdornerHelper), new PropertyMetadata(null, OnElementChanged));
		/// <summary>
		/// Element 属性变更回调。
		/// </summary>
		private static void OnElementChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			if(d is UIElement element)
			{
				if(e.OldValue != null)
				{
					RemoveAdorner(element);
					UnregisterIsVisibleChanged(element);
					UnregisterDataContextChanged(element);
				}

				if(e.NewValue != null)
				{
					RegisterIsVisibleChanged(element);
					RegisterDataContextChanged(element);

					// 同步 DataContext
					if(element is FrameworkElement fe && GetAdornerChild(e.NewValue) is FrameworkElement newChild)
					{
						newChild.DataContext = fe.DataContext;
					}

					UpdateAdornerVisibility(element);
				}
			}
		}
		#endregion

		#region 装饰层
		/// <summary>
		/// 获取当前附加的 Adorner。
		/// </summary>
		private static Adorner GetTheAdorner(DependencyObject obj) => (Adorner)obj.GetValue(TheAdornerProperty);
		/// <summary>
		/// 设置当前附加的 Adorner。
		/// </summary>
		private static void SetTheAdorner(DependencyObject obj, Adorner value) => obj.SetValue(TheAdornerProperty, value);
		private static readonly DependencyProperty TheAdornerProperty =
			DependencyProperty.RegisterAttached("TheAdorner", typeof(Adorner), typeof(AttachAdornerHelper), new PropertyMetadata(null));
		#endregion

		#region 事件注册
		/// <summary>
		/// 注册元素的 IsVisibleChanged 事件。
		/// </summary>
		private static void RegisterIsVisibleChanged(UIElement element)
		{
			if(element == null)
				return;
			element.IsVisibleChanged -= Element_IsVisibleChanged;
			element.IsVisibleChanged += Element_IsVisibleChanged;
		}
		/// <summary>
		/// 注销元素的 IsVisibleChanged 事件。
		/// </summary>
		private static void UnregisterIsVisibleChanged(UIElement element)
		{
			if(element == null)
				return;
			element.IsVisibleChanged -= Element_IsVisibleChanged;
		}
		/// <summary>
		/// 注册元素的 DataContextChanged 事件。
		/// </summary>
		private static void RegisterDataContextChanged(UIElement element)
		{
			if(element is FrameworkElement fe)
			{
				fe.DataContextChanged -= Element_DataContextChanged;
				fe.DataContextChanged += Element_DataContextChanged;
			}
		}
		/// <summary>
		/// 注销元素的 DataContextChanged 事件。
		/// </summary>
		private static void UnregisterDataContextChanged(UIElement element)
		{
			if(element is FrameworkElement fe)
			{
				fe.DataContextChanged -= Element_DataContextChanged;
			}
		}
		#endregion

		#region 方法
		/// <summary>
		/// 附加元素可见性变更事件处理。
		/// </summary>
		private static void Element_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
		{
			if(sender is UIElement element)
			{
				UpdateAdornerVisibility(element);
			}
		}

		/// <summary>
		/// 根据元素可见性和 IsShowAdorner 属性决定是否显示装饰层。
		/// </summary>
		private static void UpdateAdornerVisibility(UIElement element)
		{
			if(element.IsVisible && GetIsShowAdorner(element))
			{
				AddOrUpdateAdorner(element);
			}
			else
			{
				RemoveAdorner(element);
			}
		}

		/// <summary>
		/// 添加或更新装饰层。
		/// </summary>
		private static void AddOrUpdateAdorner(UIElement element)
		{
			try
			{
				var adornerLayer = AdornerLayer.GetAdornerLayer(element);
				if(adornerLayer == null)
					return;

				var adorners = adornerLayer.GetAdorners(element);
				if(adorners != null && adorners.Length > 0)
					return;

				var content = GetElement(element);
				if(content == null)
					return;

				var theAdorner = GetTheAdorner(element) as BindableContainerAdorner;
				if(theAdorner == null)
				{
					var child = GetAdornerChild(content);
					theAdorner = new BindableContainerAdorner(element) {Child = child};
					SetTheAdorner(element, theAdorner);
				}
				else
				{
					if(adorners?.Contains(theAdorner) ?? false)
					{
						adornerLayer.Remove(theAdorner);
					}
				}

				adornerLayer.Add(theAdorner);
			}
			catch (Exception ex)
			{
				Console.WriteLine(ex);
			}
		}

		/// <summary>
		/// 获取 Adorner 的内容（支持 DataTemplate 或 FrameworkElement）。
		/// </summary>
		private static FrameworkElement GetAdornerChild(object content)
		{
			if(content is DataTemplate dt)
			{
				return dt.LoadContent() as FrameworkElement;
			}
			return content as FrameworkElement;
		}

		/// <summary>
		/// 移除装饰层。
		/// </summary>
		private static void RemoveAdorner(UIElement element)
		{
			var adornerLayer = AdornerLayer.GetAdornerLayer(element);
			if(adornerLayer == null)
				return;

			var adorner = GetTheAdorner(element);
			if(adorner != null)
			{
				adornerLayer.Remove(adorner);
			}
		}

		/// <summary>
		/// 附加元素 DataContext 变更事件处理，将 DataContext 同步到装饰内容。
		/// </summary>
		private static void Element_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
		{
			if(sender is FrameworkElement fe)
			{
				var child = GetElement(fe);
				if(GetAdornerChild(child) is FrameworkElement childFe)
				{
					childFe.DataContext = e.NewValue;
				}
			}
		}
		#endregion
	}
}
